import { replyStore } from '../config/index';
import { paramsInUrl } from '../constants/index';
import { skipIncludes } from './commom';
import { handleStrRef } from './handleSchema';
import logger from './logger';

export function findIsUrl (url: string, namespace: string[]) {
	for (const path of namespace) {
		if (url.startsWith(path)) return true;
	}
	return false;
}

export function findReqRefClass (key: string, properties: Record<string, any>) {
	const {
		$ref, items, originalRef
	} = properties[key];
	// 特殊场景：items: { type: "integer", format: "int32" }
	return $ref || originalRef || items?.$ref || items?.originalRef || items?.type;
}

export function findResRefClass (response: ResponseProps) {
	return response?.schema?.originalRef || response?.schema?.$ref || 'any';
}

export function filterStateAble (Sw2ts: Sw2tsType, data: SwaggerSpec) {
	const mapState: Record<string, DefinitionSpec> = Object.create(null);

	for (const key in data.definitions) {
		const letter = handleStrRef(key);
		const definition = data.definitions[key];
		if (Sw2ts.requireCtx.has(letter)) {
			definition.__r__ = true;
		}

		if (definition.properties) {
			mapState[letter] = definition;

			// definitions: { IPage«MapListResponse» : Object }
			// definitions: { BaseResponse«List«HashMap«string,string»»» : Object }
			if (Sw2ts.hasContext.has(letter)) {
				const properties = definition.properties ?? Object.create(null);
				for (const property in properties) {
					const strRef = findReqRefClass(property, properties);
					if (strRef && strRef.startsWith('#')) {
						const key = strRef.split('/').pop();
						Sw2ts.hasContext.add(handleStrRef(strRef));
						if (data.definitions[key]) {
							data.definitions[key].__r__ = true;
						}
					}
				}
			}
		}

	}

	return {
		ableState: mapState,
		hasContext: Sw2ts.hasContext
	};
}

export function findRefInSchema (schema: SchemaItemFace) {
	return schema?.$ref || schema?.originalRef || schema?.items?.$ref;
}

function predict (method: string, key: string) {
	return ['get'].includes(method) && key === 'body';
}

export function combineParameters (parameters: ParameterFace[], schema: SchemaContentFace) {
	const workable = replyStore();

	for (const parameter of parameters) {
		let key = parameter.in ?? 'query';
		if (predict(schema.method, key)) {
			key = 'query';
			logger.warn(`Please modify ${schema.method} url ${schema.url}, because parameters in ${parameter.in}`);
		}

		const __ob__ = workable[key];
		if (__ob__) {
			// parameters example:
			// query { type: "array", items: { type: 'array', items: { type: 'string' } } }
			const {
				name, type, schema, items, required
			} = parameter;
			if (skipIncludes(parameter)) continue;
			const value = {
				in: parameter.in,
				required,
				name: name,
				type: type || schema?.type,
				ref: items?.type || schema?.$ref || schema?.items?.$ref
			};

			if (paramsInUrl.includes(key)) {
				__ob__[name] = value;
			} else {
				__ob__['payload'] = value;
			}
		}
	}

	for (const key in workable) {
		const value = workable[key];
		if (Object.keys(value).length < 1) {
			Reflect.deleteProperty(workable, key);
		}
	}
	return workable;
}
